"""
cURL命令执行器
负责安全地执行curl命令并返回结果
"""
import subprocess
import logging
import time
import signal
from typing import Dict, Optional
from .validator import CurlValidator

logger = logging.getLogger(__name__)


class CurlExecutor:
    """cURL命令执行器"""
    
    # 执行超时时间（秒）
    EXECUTION_TIMEOUT = 30
    
    # 最大响应大小（字节）
    MAX_RESPONSE_SIZE = 10 * 1024 * 1024  # 10MB
    
    def __init__(self):
        self.validator = CurlValidator()
        self.logger = logger
    
    def execute_curl(self, curl_command: str) -> Dict:
        """
        执行curl命令
        
        Args:
            curl_command: curl命令字符串
            
        Returns:
            dict: 执行结果
        """
        result = {
            'success': False,
            'response_data': None,
            'error': None,
            'warnings': [],
            'execution_time': 0
        }
        
        start_time = time.time()
        
        try:
            # 验证命令
            validation_result = self.validator.validate_command(curl_command)
            if not validation_result['valid']:
                result['error'] = f"命令验证失败: {validation_result['error']}"
                return result
            
            # 收集验证警告
            result['warnings'].extend(validation_result.get('warnings', []))
            
            # 清理命令
            sanitized_command = self.validator.sanitize_command(curl_command)
            
            # 构建安全的curl命令
            safe_command = self._build_safe_command(sanitized_command)
            
            self.logger.info(f"执行curl命令: {safe_command}")
            
            # 执行命令
            execution_result = self._execute_command(safe_command)
            
            if execution_result['success']:
                # 解析响应
                response_data = self._parse_response(execution_result)
                result['response_data'] = response_data
                result['success'] = True
                
                self.logger.info(f"curl命令执行成功，响应大小: {len(str(response_data))}")
            else:
                result['error'] = execution_result['error']
                
        except Exception as e:
            self.logger.error(f"curl命令执行异常: {e}")
            result['error'] = f"执行过程中发生错误: {str(e)}"
        
        finally:
            result['execution_time'] = time.time() - start_time
        
        return result
    
    def _build_safe_command(self, curl_command: str) -> list:
        """
        构建安全的curl命令参数列表
        
        Args:
            curl_command: 清理后的curl命令
            
        Returns:
            list: 命令参数列表
        """
        # 添加安全参数
        safe_params = [
            '--max-time', str(self.EXECUTION_TIMEOUT),  # 最大执行时间
            '--max-filesize', str(self.MAX_RESPONSE_SIZE),  # 最大文件大小
            '--location',  # 跟随重定向
            '--silent',  # 静默模式
            '--show-error',  # 显示错误
            '--include',  # 包含响应头
            '--compressed',  # 支持压缩
            '--user-agent', 'BrowserProxy/1.0',  # 自定义User-Agent
            '--globoff',  # 禁用URL通配符，避免特殊字符问题
        ]
        
        # 解析原始命令
        import shlex
        try:
            original_args = shlex.split(curl_command)
        except ValueError as e:
            self.logger.error(f"命令解析失败: {e}")
            raise ValueError(f"命令格式错误: {e}")
        
        # 移除curl命令本身
        if original_args and original_args[0].lower() == 'curl':
            original_args = original_args[1:]
        
                            # 清理参数，处理可能的特殊字符问题
        cleaned_args = self._clean_arguments(original_args)
        
        # 构建最终命令
        final_command = ['curl'] + safe_params + cleaned_args
        
        # 记录命令详情用于调试
        self.logger.debug(f"构建的curl命令参数数量: {len(final_command)}")
        self.logger.debug(f"命令总长度: {sum(len(arg) for arg in final_command)}")
        
        return final_command
    
    def _clean_arguments(self, args: list) -> list:
        """
        清理curl参数，处理可能导致问题的特殊字符
        
        Args:
            args: 原始参数列表
            
        Returns:
            list: 清理后的参数列表
        """
        cleaned_args = []
        
        for i, arg in enumerate(args):
            # 如果是cookie参数的值，进行特殊处理
            if i > 0 and args[i-1] in ['-b', '--cookie']:
                # 清理cookie中可能有问题的字符
                cleaned_cookie = self._clean_cookie_value(arg)
                cleaned_args.append(cleaned_cookie)
            else:
                cleaned_args.append(arg)
        
        return cleaned_args
    
    def _clean_cookie_value(self, cookie_value: str) -> str:
        """
        清理cookie值中可能导致curl错误的字符
        
        Args:
            cookie_value: 原始cookie值
            
        Returns:
            str: 清理后的cookie值
        """
        # 移除可能导致问题的字符，但保持cookie的基本结构
        # 注意：这里需要谨慎，不能破坏cookie的有效性
        
        # 如果cookie太长，截断到合理长度
        if len(cookie_value) > 4000:  # curl命令行有长度限制
            self.logger.warning(f"Cookie过长 ({len(cookie_value)} 字符)，将被截断")
            # 尝试智能截断：保留前面的重要cookie，丢弃后面的
            cookie_parts = cookie_value.split(';')
            truncated_parts = []
            current_length = 0
            
            for part in cookie_parts:
                if current_length + len(part) + 1 < 3000:  # 留一些余量
                    truncated_parts.append(part.strip())
                    current_length += len(part) + 1
                else:
                    break
            
            cookie_value = '; '.join(truncated_parts)
            self.logger.info(f"Cookie截断后长度: {len(cookie_value)}")
        
        return cookie_value
    
    def _execute_command(self, command: list) -> Dict:
        """
        执行命令
        
        Args:
            command: 命令参数列表
            
        Returns:
            dict: 执行结果
        """
        result = {
            'success': False,
            'stdout': '',
            'stderr': '',
            'return_code': None,
            'error': None
        }
        
        try:
            # 执行命令
            process = subprocess.Popen(
                command,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                text=True,
                preexec_fn=None,  # 安全考虑
                shell=False  # 不使用shell
            )
            
            # 等待执行完成
            stdout, stderr = process.communicate(timeout=self.EXECUTION_TIMEOUT)
            
            result['stdout'] = stdout
            result['stderr'] = stderr
            result['return_code'] = process.returncode
            
            if process.returncode == 0:
                result['success'] = True
            else:
                result['error'] = f"命令执行失败 (退出码: {process.returncode}): {stderr}"
                
        except subprocess.TimeoutExpired:
            result['error'] = f"命令执行超时 ({self.EXECUTION_TIMEOUT}秒)"
            try:
                process.kill()
                process.wait()
            except:
                pass
                
        except Exception as e:
            result['error'] = f"命令执行异常: {str(e)}"
        
        return result
    
    def _parse_response(self, execution_result: Dict) -> Dict:
        """
        解析curl响应
        
        Args:
            execution_result: 命令执行结果
            
        Returns:
            dict: 解析后的响应数据
        """
        stdout = execution_result.get('stdout', '')
        
        response_data = {
            'status_code': None,
            'headers': {},
            'content': '',
            'content_type': None,
            'raw_response': stdout
        }
        
        try:
            # 分离响应头和响应体
            parts = stdout.split('\r\n\r\n', 1)
            if len(parts) < 2:
                parts = stdout.split('\n\n', 1)
            
            if len(parts) >= 2:
                headers_text = parts[0]
                content = parts[1]
            else:
                headers_text = stdout
                content = ''
            
            # 解析响应头
            headers_info = self._parse_headers(headers_text)
            response_data.update(headers_info)
            
            # 设置响应内容
            response_data['content'] = content.strip()
            
            # 尝试美化JSON内容
            if response_data.get('content_type', '').startswith('application/json'):
                try:
                    import json
                    json_data = json.loads(content)
                    response_data['content'] = json.dumps(json_data, indent=2, ensure_ascii=False)
                except:
                    pass  # 保持原始内容
                    
        except Exception as e:
            self.logger.warning(f"响应解析警告: {e}")
            response_data['content'] = stdout
        
        return response_data
    
    def _parse_headers(self, headers_text: str) -> Dict:
        """
        解析HTTP响应头
        
        Args:
            headers_text: 响应头文本
            
        Returns:
            dict: 解析结果
        """
        result = {
            'status_code': None,
            'headers': {},
            'content_type': None
        }
        
        try:
            lines = headers_text.strip().split('\n')
            
            # 解析状态行
            if lines:
                status_line = lines[0].strip()
                # HTTP/1.1 200 OK
                parts = status_line.split(' ', 2)
                if len(parts) >= 2:
                    try:
                        result['status_code'] = int(parts[1])
                    except:
                        pass
            
            # 解析响应头
            headers = {}
            for line in lines[1:]:
                line = line.strip()
                if ':' in line:
                    key, value = line.split(':', 1)
                    key = key.strip()
                    value = value.strip()
                    headers[key] = value
                    
                    # 提取Content-Type
                    if key.lower() == 'content-type':
                        result['content_type'] = value.split(';')[0].strip()
            
            result['headers'] = headers
            
        except Exception as e:
            self.logger.warning(f"响应头解析警告: {e}")
        
        return result